home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Software Money Savers / VirtualDub / Source / VirtualDub-1.7.7-src.7z / src / Kasumi / source / pixmaputils.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-10-13  |  12.3 KB  |  445 lines

  1. #include <vd2/Kasumi/pixmaputils.h>
  2. #include <vd2/system/memory.h>
  3.  
  4. extern VDPixmapFormatInfo g_vdPixmapFormats[] = {
  5.     /* Null */            { "null",        0, 0, 0, 0, 0, 0, 0, 0,   0 },
  6.     /* Pal1 */            { "Pal1",        8, 1, 3, 0, 1, 0, 0, 0,   2 },
  7.     /* Pal2 */            { "Pal2",        4, 1, 2, 0, 1, 0, 0, 0,   4 },
  8.     /* Pal4 */            { "Pal4",        2, 1, 1, 0, 1, 0, 0, 0,  16 },
  9.     /* Pal8 */            { "Pal8",        1, 1, 0, 0, 1, 0, 0, 0, 256 },
  10.     /* RGB16_555 */        { "XRGB1555",    1, 1, 0, 0, 2, 0, 0, 0,   0 },
  11.     /* RGB16_565 */        { "RGB565",        1, 1, 0, 0, 2, 0, 0, 0,   0 },
  12.     /* RGB24 */            { "RGB888",        1, 1, 0, 0, 3, 0, 0, 0,   0 },
  13.     /* RGB32 */            { "XRGB8888",    1, 1, 0, 0, 4, 0, 0, 0,   0 },
  14.     /* Y8 */            { "Y8",            1, 1, 0, 0, 1, 0, 0, 0,   0 },
  15.     /* YUV422_UYVY */    { "UYVY",        2, 1, 1, 0, 4, 0, 0, 0,   0 },
  16.     /* YUV422_YUYV */    { "YUYV",        2, 1, 1, 0, 4, 0, 0, 0,   0 },
  17.     /* YUV444_XVYU */    { "XVYU",        1, 1, 0, 0, 4, 0, 0, 0,   0 },
  18.     /* YUV444_Planar */    { "YUV444",        1, 1, 0, 0, 1, 2, 0, 0,   0 },
  19.     /* YUV422_Planar */    { "YUV422",        1, 1, 0, 0, 1, 2, 1, 0,   0 },
  20.     /* YUV420_Planar */    { "YUV420",        1, 1, 0, 0, 1, 2, 1, 1,   0 },
  21.     /* YUV411_Planar */    { "YUV411",        1, 1, 0, 0, 1, 2, 2, 0,   0 },
  22.     /* YUV410_Planar */    { "YUV410",        1, 1, 0, 0, 1, 2, 2, 2,   0 },
  23. };
  24.  
  25. #ifdef _DEBUG
  26.     bool VDIsValidPixmapPlane(const void *p, ptrdiff_t pitch, vdpixsize w, vdpixsize h) {
  27.         bool isvalid;
  28.  
  29.         if (pitch < 0)
  30.             isvalid = VDIsValidReadRegion((const char *)p + pitch*(h-1), (-pitch)*(h-1)+w);
  31.         else
  32.             isvalid = VDIsValidReadRegion(p, pitch*(h-1)+w);
  33.  
  34.         if (!isvalid) {
  35.             VDDEBUG("Kasumi: Invalid pixmap plane detected.\n"
  36.                     "        Base=%p, pitch=%d, size=%dx%d (bytes)\n", p, (int)pitch, w, h);
  37.         }
  38.  
  39.         return isvalid;
  40.     }
  41.  
  42.     bool VDAssertValidPixmap(const VDPixmap& px) {
  43.         const VDPixmapFormatInfo& info = VDPixmapGetInfo(px.format);
  44.  
  45.         if (px.format) {
  46.             if (!VDIsValidPixmapPlane(px.data, px.pitch, -(-px.w >> info.qwbits)*info.qsize, -(-px.h >> info.qhbits))) {
  47.                 VDDEBUG("Kasumi: Invalid primary plane detected in pixmap.\n"
  48.                         "        Pixmap info: format=%d, dimensions=%dx%d\n", px.format, px.w, px.h);
  49.                 VDASSERT(!"Kasumi: Invalid primary plane detected in pixmap.\n");
  50.                 return false;
  51.             }
  52.  
  53.             if (info.palsize)
  54.                 if (!VDIsValidReadRegion(px.palette, sizeof(uint32) * info.palsize)) {
  55.                     VDDEBUG("Kasumi: Invalid palette detected in pixmap.\n"
  56.                             "        Pixmap info: format=%d, dimensions=%dx%d\n", px.format, px.w, px.h);
  57.                     VDASSERT(!"Kasumi: Invalid palette detected in pixmap.\n");
  58.                     return false;
  59.                 }
  60.  
  61.             if (info.auxbufs) {
  62.                 const vdpixsize auxw = -(-px.w >> info.auxwbits);
  63.                 const vdpixsize auxh = -(-px.h >> info.auxhbits);
  64.  
  65.                 if (!VDIsValidPixmapPlane(px.data2, px.pitch2, auxw, auxh)) {
  66.                     VDDEBUG("Kasumi: Invalid Cb plane detected in pixmap.\n"
  67.                             "        Pixmap info: format=%d, dimensions=%dx%d\n", px.format, px.w, px.h);
  68.                     VDASSERT(!"Kasumi: Invalid Cb plane detected in pixmap.\n");
  69.                     return false;
  70.                 }
  71.  
  72.                 if (info.auxbufs > 2) {
  73.                     if (!VDIsValidPixmapPlane(px.data3, px.pitch3, auxw, auxh)) {
  74.                         VDDEBUG("Kasumi: Invalid Cr plane detected in pixmap.\n"
  75.                                 "        Pixmap info: format=%d, dimensions=%dx%d\n", px.format, px.w, px.h);
  76.                         VDASSERT(!"Kasumi: Invalid Cr plane detected in pixmap.\n");
  77.                         return false;
  78.                     }
  79.                 }
  80.             }
  81.         }
  82.  
  83.         return true;
  84.     }
  85. #endif
  86.  
  87. VDPixmap VDPixmapOffset(const VDPixmap& src, vdpixpos x, vdpixpos y) {
  88.     VDPixmap temp(src);
  89.     const VDPixmapFormatInfo& info = VDPixmapGetInfo(temp.format);
  90.  
  91.     x >>= info.qwbits;
  92.     y >>= info.qhbits;
  93.  
  94.     switch(info.auxbufs) {
  95.     case 2:
  96.         temp.data3 = (char *)temp.data3 + (x >> info.auxwbits) + (y >> info.auxhbits)*temp.pitch3;
  97.     case 1:
  98.         temp.data2 = (char *)temp.data2 + (x >> info.auxwbits) + (y >> info.auxhbits)*temp.pitch2;
  99.     case 0:
  100.         temp.data = (char *)temp.data + x*info.qsize + y*temp.pitch;
  101.     }
  102.  
  103.     return temp;
  104. }
  105.  
  106. VDPixmapLayout VDPixmapLayoutOffset(const VDPixmapLayout& src, vdpixpos x, vdpixpos y) {
  107.     VDPixmapLayout temp(src);
  108.     const VDPixmapFormatInfo& info = VDPixmapGetInfo(temp.format);
  109.  
  110.     x = -(-x >> info.qwbits);
  111.     y = -(-y >> info.qhbits);
  112.  
  113.     switch(info.auxbufs) {
  114.     case 2:
  115.         temp.data3 += -(-x >> info.auxwbits) + -(-y >> info.auxhbits)*temp.pitch3;
  116.     case 1:
  117.         temp.data2 += -(-x >> info.auxwbits) + -(-y >> info.auxhbits)*temp.pitch2;
  118.     case 0:
  119.         temp.data += x*info.qsize + y*temp.pitch;
  120.     }
  121.  
  122.     return temp;
  123. }
  124.  
  125. uint32 VDPixmapCreateLinearLayout(VDPixmapLayout& layout, int format, vdpixsize w, vdpixsize h, int alignment) {
  126.     const ptrdiff_t alignmask = alignment - 1;
  127.  
  128.     const VDPixmapFormatInfo& srcinfo = VDPixmapGetInfo(format);
  129.     sint32        qw            = -(-w >> srcinfo.qwbits);
  130.     sint32        qh            = -(-h >> srcinfo.qhbits);
  131.     sint32        subw        = -(-w >> srcinfo.auxwbits);
  132.     sint32        subh        = -(-h >> srcinfo.auxhbits);
  133.  
  134.     ptrdiff_t    mainpitch    = (srcinfo.qsize * qw + alignmask) & ~alignmask;
  135.     size_t        mainsize    = mainpitch * qh;
  136.  
  137.     layout.data        = 0;
  138.     layout.pitch    = mainpitch;
  139.     layout.palette    = NULL;
  140.     layout.data2    = 0;
  141.     layout.pitch2    = 0;
  142.     layout.data3    = 0;
  143.     layout.pitch3    = 0;
  144.     layout.w        = w;
  145.     layout.h        = h;
  146.     layout.format    = format;
  147.  
  148.     if (srcinfo.auxbufs >= 1) {
  149.         ptrdiff_t    subpitch    = (subw + alignmask) & ~alignmask;
  150.         size_t        subsize        = subpitch * subh;
  151.  
  152.         layout.data2    = mainsize;
  153.         layout.pitch2    = subpitch;
  154.         mainsize += subsize;
  155.  
  156.         if (srcinfo.auxbufs >= 2) {
  157.             layout.data3    = mainsize;
  158.             layout.pitch3    = subpitch;
  159.             mainsize += subsize;
  160.         }
  161.     }
  162.  
  163.     return mainsize;
  164. }
  165.  
  166. void VDPixmapFlipV(VDPixmap& px) {
  167.     const VDPixmapFormatInfo& srcinfo = VDPixmapGetInfo(px.format);
  168.     sint32        w            = px.w;
  169.     sint32        h            = px.h;
  170.     sint32        qw            = -(-w >> srcinfo.qwbits);
  171.     sint32        qh            = -(-h >> srcinfo.qhbits);
  172.     sint32        subw        = -(-w >> srcinfo.auxwbits);
  173.     sint32        subh        = -(-h >> srcinfo.auxhbits);
  174.  
  175.     vdptrstep(px.data, px.pitch * (qh - 1));
  176.     px.pitch = -px.pitch;
  177.  
  178.     if (srcinfo.auxbufs >= 1) {
  179.         vdptrstep(px.data2, px.pitch2 * (subh - 1));
  180.         px.pitch2 = -px.pitch2;
  181.  
  182.         if (srcinfo.auxbufs >= 2) {
  183.             vdptrstep(px.data3, px.pitch3 * (subh - 1));
  184.             px.pitch3 = -px.pitch3;
  185.         }
  186.     }
  187. }
  188.  
  189. void VDPixmapLayoutFlipV(VDPixmapLayout& layout) {
  190.     const VDPixmapFormatInfo& srcinfo = VDPixmapGetInfo(layout.format);
  191.     sint32        w            = layout.w;
  192.     sint32        h            = layout.h;
  193.     sint32        qw            = -(-w >> srcinfo.qwbits);
  194.     sint32        qh            = -(-h >> srcinfo.qhbits);
  195.     sint32        subw        = -(-w >> srcinfo.auxwbits);
  196.     sint32        subh        = -(-h >> srcinfo.auxhbits);
  197.  
  198.     layout.data += layout.pitch * (qh - 1);
  199.     layout.pitch = -layout.pitch;
  200.  
  201.     if (srcinfo.auxbufs >= 1) {
  202.         layout.data2 += layout.pitch2 * (subh - 1);
  203.         layout.pitch2 = -layout.pitch2;
  204.  
  205.         if (srcinfo.auxbufs >= 2) {
  206.             layout.data3 += layout.pitch3 * (subh - 1);
  207.             layout.pitch3 = -layout.pitch3;
  208.         }
  209.     }
  210. }
  211.  
  212. ///////////////////////////////////////////////////////////////////////////
  213.  
  214. VDPixmapBuffer::VDPixmapBuffer(const VDPixmap& src)
  215.     : mpBuffer(NULL)
  216.     , mLinearSize(0)
  217. {
  218.     assign(src);
  219. }
  220.  
  221. VDPixmapBuffer::VDPixmapBuffer(const VDPixmapBuffer& src)
  222.     : mpBuffer(NULL)
  223.     , mLinearSize(0)
  224. {
  225.     assign(src);
  226. }
  227.  
  228. VDPixmapBuffer::VDPixmapBuffer(const VDPixmapLayout& layout) {
  229.     init(layout);
  230. }
  231.  
  232. VDPixmapBuffer::~VDPixmapBuffer() {
  233. #ifdef _DEBUG
  234.     validate();
  235. #endif
  236.  
  237.     delete[] mpBuffer;
  238. }
  239.  
  240. void VDPixmapBuffer::init(sint32 width, sint32 height, int f) {
  241.     const VDPixmapFormatInfo& srcinfo = VDPixmapGetInfo(f);
  242.     sint32        qw            = -(-width >> srcinfo.qwbits);
  243.     sint32        qh            = -(-height >> srcinfo.qhbits);
  244.     sint32        subw        = -(-width >> srcinfo.auxwbits);
  245.     sint32        subh        = -(-height >> srcinfo.auxhbits);
  246.     ptrdiff_t    mainpitch    = (srcinfo.qsize * qw + 15) & ~15;
  247.     ptrdiff_t    subpitch    = (subw + 15) & ~15;
  248.     size_t        mainsize    = mainpitch * qh;
  249.     size_t        subsize        = subpitch * subh;
  250.     size_t        totalsize    = mainsize + subsize*srcinfo.auxbufs + 4 * srcinfo.palsize;
  251.  
  252. #ifdef _DEBUG
  253.     totalsize += 28;
  254. #endif
  255.  
  256.     if (mLinearSize != totalsize) {
  257.         clear();
  258.         mpBuffer = new char[totalsize + 15];
  259.         mLinearSize = totalsize;
  260.     }
  261.  
  262.     char *p = mpBuffer + (-(int)(uintptr)mpBuffer & 15);
  263.  
  264. #ifdef _DEBUG
  265.     *(uint32 *)p = totalsize;
  266.     for(int i=0; i<12; ++i)
  267.         p[4+i] = (char)(0xa0 + i);
  268.  
  269.     p += 16;
  270. #endif
  271.  
  272.     data    = p;
  273.     pitch    = mainpitch;
  274.     p += mainsize;
  275.  
  276.     palette    = NULL;
  277.     data2    = NULL;
  278.     pitch2    = NULL;
  279.     data3    = NULL;
  280.     pitch3    = NULL;
  281.     w        = width;
  282.     h        = height;
  283.     format    = f;
  284.  
  285.     if (srcinfo.auxbufs >= 1) {
  286.         data2    = p;
  287.         pitch2    = subpitch;
  288.         p += subsize;
  289.     }
  290.  
  291.     if (srcinfo.auxbufs >= 2) {
  292.         data3    = p;
  293.         pitch3    = subpitch;
  294.         p += subsize;
  295.     }
  296.  
  297.     if (srcinfo.palsize) {
  298.         palette = (const uint32 *)p;
  299.         p += srcinfo.palsize * 4;
  300.     }
  301.  
  302. #ifdef _DEBUG
  303.     for(int j=0; j<12; ++j)
  304.         p[j] = (char)(0xb0 + j);
  305. #endif
  306. }
  307.  
  308. void VDPixmapBuffer::init(const VDPixmapLayout& layout) {
  309.     const VDPixmapFormatInfo& srcinfo = VDPixmapGetInfo(layout.format);
  310.     sint32        qw            = -(-layout.w >> srcinfo.qwbits);
  311.     sint32        qh            = -(-layout.h >> srcinfo.qhbits);
  312.     sint32        subw        = -(-layout.w >> srcinfo.auxwbits);
  313.     sint32        subh        = -(-layout.h >> srcinfo.auxhbits);
  314.  
  315.     ptrdiff_t mino=0, maxo=0;
  316.  
  317.     if (layout.pitch < 0) {
  318.         mino = std::min<ptrdiff_t>(mino, layout.data + layout.pitch * (qh-1));
  319.         maxo = std::max<ptrdiff_t>(maxo, layout.data - layout.pitch);
  320.     } else {
  321.         mino = std::min<ptrdiff_t>(mino, layout.data);
  322.         maxo = std::max<ptrdiff_t>(maxo, layout.data + layout.pitch*qh);
  323.     }
  324.  
  325.     if (srcinfo.auxbufs >= 1) {
  326.         if (layout.pitch2 < 0) {
  327.             mino = std::min<ptrdiff_t>(mino, layout.data2 + layout.pitch2 * (subh-1));
  328.             maxo = std::max<ptrdiff_t>(maxo, layout.data2 - layout.pitch2);
  329.         } else {
  330.             mino = std::min<ptrdiff_t>(mino, layout.data2);
  331.             maxo = std::max<ptrdiff_t>(maxo, layout.data2 + layout.pitch2*subh);
  332.         }
  333.  
  334.         if (srcinfo.auxbufs >= 2) {
  335.             if (layout.pitch3 < 0) {
  336.                 mino = std::min<ptrdiff_t>(mino, layout.data3 + layout.pitch3 * (subh-1));
  337.                 maxo = std::max<ptrdiff_t>(maxo, layout.data3 - layout.pitch3);
  338.             } else {
  339.                 mino = std::min<ptrdiff_t>(mino, layout.data3);
  340.                 maxo = std::max<ptrdiff_t>(maxo, layout.data3 + layout.pitch3*subh);
  341.             }
  342.         }
  343.     }
  344.  
  345.     ptrdiff_t linsize = ((maxo - mino + 3) & ~(uintptr)3);
  346.  
  347.     ptrdiff_t totalsize = linsize + 4*srcinfo.palsize;
  348.  
  349. #ifdef _DEBUG
  350.     totalsize += 28;
  351. #endif
  352.  
  353.     if (mLinearSize != totalsize) {
  354.         clear();
  355.         mpBuffer = new char[totalsize + 15];
  356.         mLinearSize = totalsize;
  357.     }
  358.  
  359.     char *p = mpBuffer + (-(int)(uintptr)mpBuffer & 15);
  360.  
  361. #ifdef _DEBUG
  362.     *(uint32 *)p = totalsize - 28;
  363.     for(int i=0; i<12; ++i)
  364.         p[4+i] = (char)(0xa0 + i);
  365.  
  366.     p += 16;
  367. #endif
  368.  
  369.     w        = layout.w;
  370.     h        = layout.h;
  371.     format    = layout.format;
  372.     data    = p + layout.data - mino;
  373.     data2    = p + layout.data2 - mino;
  374.     data3    = p + layout.data3 - mino;
  375.     pitch    = layout.pitch;
  376.     pitch2    = layout.pitch2;
  377.     pitch3    = layout.pitch3;
  378.     palette    = NULL;
  379.  
  380.     if (srcinfo.palsize) {
  381.         palette = (const uint32 *)(p + linsize);
  382.         memcpy((void *)palette, layout.palette, 4*srcinfo.palsize);
  383.     }
  384.  
  385. #ifdef _DEBUG
  386.     for(int j=0; j<12; ++j)
  387.         p[totalsize + j - 28] = (char)(0xb0 + j);
  388. #endif
  389.  
  390.     VDAssertValidPixmap(*this);
  391. }
  392.  
  393. void VDPixmapBuffer::assign(const VDPixmap& src) {
  394.     if (!src.format) {
  395.         delete[] mpBuffer;
  396.         mpBuffer = NULL;
  397.         data = NULL;
  398.         format = 0;
  399.     } else {
  400.         init(src.w, src.h, src.format);
  401.  
  402.         const VDPixmapFormatInfo& srcinfo = VDPixmapGetInfo(src.format);
  403.         int qw = (src.w >> srcinfo.qwbits);
  404.         int qh = src.h >> srcinfo.qhbits;
  405.         int subw = -(-src.w >> srcinfo.auxwbits);
  406.         int subh = -(-src.h >> srcinfo.auxhbits);
  407.  
  408.         if (srcinfo.palsize)
  409.             memcpy((void *)palette, src.palette, 4 * srcinfo.palsize);
  410.  
  411.         switch(srcinfo.auxbufs) {
  412.         case 2:
  413.             VDMemcpyRect(data3, pitch3, src.data3, src.pitch3, subw, subh);
  414.         case 1:
  415.             VDMemcpyRect(data2, pitch2, src.data2, src.pitch2, subw, subh);
  416.         case 0:
  417.             VDMemcpyRect(data, pitch, src.data, src.pitch, qw * srcinfo.qsize, qh);
  418.         }
  419.     }
  420. }
  421.  
  422. void VDPixmapBuffer::swap(VDPixmapBuffer& dst) {
  423.     std::swap(mpBuffer, dst.mpBuffer);
  424.     std::swap(mLinearSize, dst.mLinearSize);
  425.     std::swap(static_cast<VDPixmap&>(*this), static_cast<VDPixmap&>(dst));
  426. }
  427.  
  428. #ifdef _DEBUG
  429. void VDPixmapBuffer::validate() {
  430.     if (mpBuffer) {
  431.         char *p = (char *)(((uintptr)mpBuffer + 15) & ~(uintptr)15);
  432.  
  433.         // verify head bytes
  434.         for(int i=0; i<12; ++i)
  435.             if (p[i+4] != (char)(0xa0 + i))
  436.                 VDASSERT(!"VDPixmapBuffer: Buffer underflow detected.\n");
  437.  
  438.         // verify tail bytes
  439.         for(int j=0; j<12; ++j)
  440.             if (p[mLinearSize - 12 + j] != (char)(0xb0 + j))
  441.                 VDASSERT(!"VDPixmapBuffer: Buffer overflow detected.\n");
  442.     }
  443. }
  444. #endif
  445.